import {
  AfterViewInit,
  Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, QueryList, SimpleChanges, ViewChild,
  ViewChildren
} from '@angular/core';
import {numeral} from 'numeral';
import {Util} from "../../../common/util";
import {environment} from "environments/environment";
import {OnChange} from "../../../common/decorators";

/**
 * 银行间有关交易单列表配置数据模型
 */
export interface IBTListColumnDisplayConfigModel {
  /**
   * 是否显示checkbox单选按钮
   */
  select?: boolean;
  /**
   * 是否显示序号
   */
  index?: boolean;
  /**
   * 是否显示交易单附件操作列
   */
  file?: boolean;

  /**
   * 是否不能上传附件
   */
  unableUpload?: boolean;

  /**
   * 是否不能删除附件
   */
  unableRemoveFile?: boolean;

  /**
   * 是否启用条件背景色配置
   */
  color?: boolean;

  /**
   * 其他用户列配置
   */
  [propName: string]: boolean;
}


@Component({
  selector: 'interbank-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnInit, OnChanges, AfterViewInit {

  @Input()
  public fold = true;

  @Input()
  public o32Fold = true;

  @Input()
  public config: IBTListColumnDisplayConfigModel = {};

  @Input()
  public data: Data = {
    list: []
  };

  @Input()
  public indexOffest = 0;

  @Output()
  public uploadFile: EventEmitter<any> = new EventEmitter<any>();

  @Output()
  public removeFile: EventEmitter<any> = new EventEmitter<any>();

  @Output()
  public urgent: EventEmitter<any> = new EventEmitter<any>();

  @Output()
  public getPledgeAllData: EventEmitter<any> = new EventEmitter<any>();

  /**
   * o32相关列隐藏状态改变事件，发射true值表示折叠，false值表示展开
   * @type {EventEmitter<any>}
   */
  @Output()
  public o32FoldStautsChanged: EventEmitter<boolean> = new EventEmitter<boolean>();

  @ViewChild('selectAll')
  public selectAllBtn: ElementRef;

  @ViewChildren('select')
  public selectBtns: QueryList<ElementRef> = new QueryList<ElementRef>();

  @ViewChild('container')
  public container: ElementRef;

  @ViewChild('scrollTableContainer')
  public scrollTableContainer: ElementRef;

  @ViewChild('scrollTableHeader')
  public scrollTableHeader: ElementRef;

  @ViewChild('scrollTableBody')
  public scrollTableBody: ElementRef;

  @ViewChild('fixedTableContainer')
  public fixedTableContainer: ElementRef;

  @ViewChild('fixedTable')
  public fixedTable: ElementRef;

  @ViewChild('fixedTableHeader')
  public fixedTableHeader: ElementRef;

  @ViewChild('fixedTableBody')
  public fixedTableBody: ElementRef;

  public selectedDatas: Array<any> = [];

  constructor() {
  }

  ngOnInit() {
    this.resetFixedTableLayout();
  }

  ngOnChanges(changes: SimpleChanges): void {
    this.resetFixedTableLayout();
    if (changes.data && !changes.data.isFirstChange() && changes.data.currentValue.list !== changes.data.previousValue.list) {
      this.unSelectAll();
    }
  }

  ngAfterViewInit(): void {
  }

  /**
   *
   * 切换与o32相关的列的折叠显示状态到相反状态
   * @returns {ListComponent}
   */
  public toggleFold() {
    this.fold = !this.fold;
    return this;
  }

  /**
   * 切换与o32相关的列的折叠显示
   */
  public toggleO32Fold() {
    if (this.o32Fold) {
      this.toggleO32RefColsOpen();
    } else {
      this.toggleO32RefColsClose();
    }
  }

  /**
   * 切换与o32相关的列到显示状态，并发布o32FoldStautsChanged事件，发射值为false
   */
  public toggleO32RefColsOpen() {
    this.config.trdFundName = true;
    this.config.trdTradeType = true;
    this.config.trdInterCode = true;
    this.config.trdStockName = true;
    this.config.trdSettleBalance = true;
    this.config.trdPledgeMatchStatus = true;
    this.o32Fold = false;
    this.o32FoldStautsChanged.emit(this.o32Fold);
  }

  /**
   * 切换与o32相关的列到折叠状态，并发布o32FoldStautsChanged事件，发射值为true
   */
  public toggleO32RefColsClose() {
    this.config.trdFundName = false;
    this.config.trdTradeType = false;
    this.config.trdInterCode = false;
    this.config.trdStockName = false;
    this.config.trdSettleBalance = false;
    this.config.trdPledgeMatchStatus = false;
    this.o32Fold = true;
    this.o32FoldStautsChanged.emit(this.o32Fold);
  }

  /**
   * 切换列表到隐藏状态
   * @returns {ListComponent}
   */
  public toggleClose() {
    this.fold = true;
    return this;
  }

  /**
   * 切换列表到显示状态
   * @returns {ListComponent}
   */
  public toggleOpen() {
    this.fold = false;
    return this;
  }

  /**
   * 选择全部明细行
   */
  public selectAll() {
    this.selectAllBtn.nativeElement.checked = true;
    this.selectBtns.forEach((btn) => {
      btn.nativeElement.checked = true;
    });
    this.addAllSelectedDatas();
  }

  /**
   * 取消选择全部明细行
   */
  public unSelectAll() {
    this.selectAllBtn.nativeElement.checked = false;
    this.selectBtns.forEach((btn) => {
      btn.nativeElement.checked = false;
    });
    this.resetSelectedDatas();
  }

  /**
   * 切换全部明细行的选择状态
   */
  public toggleSelectAll() {
    if (this.selectAllBtn.nativeElement.checked) {
      this.selectAll();
    } else {
      this.unSelectAll();
    }
  }

  /**
   * 根据当前点击目标DOM元素对象和列表行索引，将其对应的数据加入选用数据数组selectedDatas中
   * @param $event
   * @param index
   */
  public selectOne($event, index) {
    const $target = $event.target;
    const checkStatus = $target.checked;
    if (!this.isAllSelect()) {
      this.selectAllBtn.nativeElement.checked = false;
    } else {
      this.selectAllBtn.nativeElement.checked = true;
    }
    this.autoAddSelectedDatas();
  }

  /**
   * 判断是否列表所有明细行都处于已被选中的状态，返回true表示列表明细行都选中了，false则表示列表明细行中存在
   * 未被选中的行
   * @returns {boolean}
   */
  public isAllSelect(): boolean {
    const result = this.selectBtns.some((btn, index) => {
      return btn.nativeElement.checked === false;
    });
    return !result;
  }

  /**
   * 获取所有被选中的明细行对应的数据数组
   * @returns {Array<any>}
   */
  public getSelectedDatas(): Array<any> {
    return this.selectedDatas;
  }

  /**
   * 重置被选中的明细行对应的数据数组为空数组
   */
  public resetSelectedDatas() {
    this.selectedDatas = [];
  }

  /**
   * 将selectBtns数组代表的已被选中的明细行对应的数据添加到selectedDatas数组中
   */
  public addAllSelectedDatas() {
    this.resetSelectedDatas();
    this.selectBtns.forEach((btn, index) => this.selectedDatas.push(this.data.list[index]));
  }

  /**
   * 将所有已被选中的明细行对应的数据添加到selectedDatas数组中
   * @returns {Array<any>}
   */
  public autoAddSelectedDatas(): Array<any> {
    this.resetSelectedDatas();
    this.selectBtns.forEach((btn, index) => {
      if (btn.nativeElement.checked) {
        this.selectedDatas.push(this.data.list[index]);
      }
    });
    return this.selectedDatas;
  }

  /**
   * 重新设置固定列的布局
   */
  public resetFixedTableLayout() {
    const $ = Util.$;
    $(this.fixedTableHeader.nativeElement)
      .find('tr')
      .each((index, item) => {
        $(item).outerHeight($(this.scrollTableHeader.nativeElement).outerHeight());
      });
    $(this.fixedTableBody.nativeElement)
      .find('tr')
      .each((index, item) => {
        const fixedRowHeight = $(item).outerHeight();
        const scrollRowHeight = $(this.scrollTableBody.nativeElement).find(`tr:nth-child(${index + 1})`).outerHeight();
        const computedRowHeight = fixedRowHeight > scrollRowHeight ? fixedRowHeight : scrollRowHeight;
        $(item).outerHeight(computedRowHeight);
      });
  }

  /**
   * 发布上传附件事件
   * @param orderSerialNo
   */
  public uploadFileAction(orderSerialNo: string, tradeOrderFileId: string, fileName: string) {
    this.uploadFile.emit({
      orderSerialNo: orderSerialNo,
      tradeOrderFileId: tradeOrderFileId,
      fileName: fileName
    });
  }

  /**
   * 发布删除附件事件
   * @param orderSerialNo
   */
  public removeFileAction(orderSerialNo: string) {
    this.removeFile.emit(orderSerialNo);
  }

  /**
   * 发布加急事件
   * @param settlementOrderId
   */
  public urgentAction(settlementOrderId: string) {
    this.urgent.emit(settlementOrderId);
  }

  /**
   * 发布获取全部质押券信息数据事件
   * @param orderSerialNo
   */
  public getPledgeAllDataAction(orderSerialNo: string) {
    this.getPledgeAllData.emit(orderSerialNo);
  }

  /**
   * 根据交易单ID生成附件下载链接
   * @param orderSerialNo
   */
  public createFileDownloadLink(orderSerialNo: string): string {
    return new window['URI'](
      environment.server + `otc/v1/chinamoney/tradeOrderFile/${orderSerialNo}/download?token=${sessionStorage.getItem('username')}`
    ).toString();
  }

  /**
   * 根据列对应的字段名和列表配置，计算该列是否需要显示，默认显示
   * @param columnName
   * @returns {boolean}
   */
  public isShowColumn(columnName: string): boolean {
    return this.config[columnName] == null ? true : ((this.config[columnName] === true) ? true : false);
  }

  /**
   * 根据列对应的字段名和列表配置，计算该列是否需要隐藏，默认隐藏
   * @param columnName
   * @returns {boolean}
   */
  public isHiddenColumn(columnName: string): boolean {
    return !this.isShowColumn(columnName);
  }
}

interface Data {
  [propName: string]: any;
  list: Array<any>;
}
